package com.mall.service.impl;

import ch.qos.logback.core.util.MD5Util;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.MD5;
import com.mall.constants.JwtClaimsConstant;
import com.mall.constants.StatusConstants;
import com.mall.context.BaseContext;
import com.mall.domain.dto.RechargeDTO;
import com.mall.domain.dto.UserDTO;
import com.mall.domain.dto.UserUpdatePasswordDTO;
import com.mall.domain.po.User;
import com.mall.domain.vo.UserLoginVO;
import com.mall.exception.LoginFailedException;
import com.mall.exception.NotAdminException;
import com.mall.mapper.UserMapper;
import com.mall.properties.JwtProperties;
import com.mall.service.UserService;
import com.mall.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author 勾新杰
 * @version 1.0
 * @date 2024/11/21 23:52
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;

    private final JwtProperties jwtProperties;

    /**
     * 用户注册，前端传过来的密码是已经加密过的
     *
     * @param userDTO 用户传输对象
     */
    @Override
    public void register(UserDTO userDTO) {
        // 1. 构建用户对象
        User user = BeanUtil.copyProperties(userDTO, User.class);
        user.setCreateTime(LocalDateTime.now());
        user.setStatus(StatusConstants.ENABLE);
        user.setBalance(0.0);
        // 密码加密
        user.setPassword(MD5.create().digestHex(user.getPassword()));
        // 2. 插入用户
        userMapper.insert(user);
    }

    /**
     * 用户登录
     *
     * @param userDTO 用户传输对象
     * @return 用户登录视图对象
     */
    @Override
    public UserLoginVO login(UserDTO userDTO) {
        // 1. 根据用户名查询用户
        User user = userMapper.getUserByUsername(userDTO.getUsername());
        // 2. 判断用户是否存在
        if (user == null) {
            throw new LoginFailedException("用户名不存在");
        }
        // 3. 判断密码是否正确
        String password = MD5.create().digestHex(userDTO.getPassword());
        if (!user.getPassword().equals(password)) {
            throw new LoginFailedException("密码错误");
        }
        // 4. 判断用户是否禁用
        if (Objects.equals(user.getStatus(), StatusConstants.DISABLE)) {
            throw new LoginFailedException("用户已禁用");
        }
        // 5. 修改最后一次登录时间
        userMapper.update(User.builder()
                .id(user.getId())
                .lastLogin(LocalDateTime.now())
                .build());
        // 6. 生成token，存入用户id和用户名，不要存密码
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID, user.getId());
        claims.put(JwtClaimsConstant.USERNAME, user.getUsername());
        // 7. 构建返回对象
        UserLoginVO userLoginVO = new UserLoginVO();
        userLoginVO.setId(user.getId());
        userLoginVO.setToken(JwtUtil.createJWT(
                jwtProperties.getSecretKey(),
                jwtProperties.getExpireTime(),
                claims));
        return userLoginVO;
    }

    /**
     * 修改密码
     *
     * @param updatePasswordDTO 修改密码传输对象
     */
    @Override
    public void changePassword(UserUpdatePasswordDTO updatePasswordDTO) {
        // 1. 获取当前用户
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.getUserById(userId);
        // 2. 判断旧密码是否正确
        if (!user.getPassword().equals(MD5.create().digestHex(updatePasswordDTO.getOldPassword()))) {
            throw new LoginFailedException("旧密码错误");
        }
        // 3. 修改密码
        userMapper.updatePassword(userId, MD5.create().digestHex(updatePasswordDTO.getNewPassword()));
    }

    /**
     * 修改用户信息
     *
     * @param userDTO 用户传输对象
     */
    @Override
    public void updateUserInfo(UserDTO userDTO) {
        // 1. 构建用户对象
        User user = BeanUtil.copyProperties(userDTO, User.class);
        // 2. 密码置空
        user.setPassword(null);
        // 4. 获取当前用户id
        user.setId(BaseContext.getCurrentId());
        // 5. 更新数据库
        userMapper.update(user);
    }

    /**
     * 修改用户状态
     *
     * @param id     用户id
     * @param status 状态
     */
    @Override
    public void updateStatus(Long id, Integer status) {
        // 1. 查看当前用户是否是管理员
        if (!Objects.equals(BaseContext.getCurrentId(), 1L)) {
            throw new NotAdminException("非管理员，无法修改用户状态");
        }
        // 2. 判断是否是要禁用管理员账号
        if (id == 1L && Objects.equals(status, StatusConstants.DISABLE)) {
            throw new NotAdminException("管理员账号禁止禁用");
        }
        // 3. 构建用户对象
        User user = User.builder()
                .id(id)
                .status(status)
                .build();
        // 4. 更新数据库
        userMapper.update(user);
    }

    /**
     * 充值
     *
     * @param rechargeDTO 充值传输对象
     */
    @Override
    public void induct(RechargeDTO rechargeDTO) {
        userMapper.inductBalance(rechargeDTO.getAmount(), BaseContext.getCurrentId());
    }

    /**
     * 扣款
     *
     * @param rechargeDTO 充值传输对象
     */
    @Override
    public void deduct(RechargeDTO rechargeDTO) {
        userMapper.deductBalance(rechargeDTO.getAmount(), BaseContext.getCurrentId());
    }
}
